package com.streambolics.worseminton.servlet;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.jdo.Query;
import javax.servlet.http.HttpServletRequest;

import com.streambolics.appengine.UserAwareServlet;
import com.streambolics.data.Person;
import com.streambolics.servlet.RequestBeanSetter;
import com.streambolics.std.HtmlBuilder;
import com.streambolics.worseminton.data.Event;
import com.streambolics.worseminton.data.Invitation;
import com.streambolics.worseminton.data.Location;
import com.streambolics.worseminton.data.LocationInterest;

public class EventHandler extends UserAwareServlet<Event>
{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    /**
     * Accesses the event represented by the URL.
     * 
     * @return An existing event if one is found based on the location and time,
     *         a new one otherwise.
     * @throws Exception
     */

    protected Event accessEvent () throws Exception
    {
        Location l = Location.load (getDatabase (), requireLongArg ("LOCID"));
        Calendar c = l.createCalendar ();
        parseRequiredDate ("DATE", c);
        parseRequiredTime ("TIME1", c);

        return accessEvent (l.getId (), c.getTime ());
    }

    protected Event accessEvent (long aLocationId, Date aTime)
    {
        String query = "select from " + Event.class.getName () + " where locationId == p_location && time == p_time";
        Query q = getDatabase ().newQuery (query);
        q.declareParameters ("Long p_location, java.util.Date p_time");
        @SuppressWarnings("unchecked")
        List<Event> found = (List<Event>) q.execute (aLocationId, aTime);

        if (found.size () > 0)
        {
            Event e = found.get (0);
            e.setDatabase (getDatabase ());
            return e;
        }
        else
        {
            return createEvent (aLocationId, aTime);
        }
    }

    protected Event addInvitation () throws Exception
    {
        Event e = getReferencedEvent ();
        mustBeUserId (e.getOwnerId ());
        return e;
    }

    protected Event createEvent (long aLocationId, Date aTime)
    {
        Event e = new Event ();
        e.setDatabase (getDatabase ());
        save (e);

        Location l = Location.load (getDatabase (), aLocationId);
        e.setOwnerId (l.getOwnerId ());
        e.setLocationId (aLocationId);
        e.setTime (aTime);
        LocationInterest ownerInterest = LocationInterest.access (getDatabase (), aLocationId, l.getOwnerId ());
        e.addGuest (ownerInterest);
        return e;
    }

    @Override
    protected void formatBodyAsSimpleDesktopHtml (HtmlBuilder aBuilder, Event aResponseObject) throws Exception
    {
        boolean canChange = hasWritePermission (aResponseObject);

        aBuilder.openDiv ("body");

        aBuilder.openElement ("<h1>");
        aBuilder.addText (aResponseObject.getDescription ());
        aBuilder.closeElement ("</h1>");

        aBuilder.openForm ("/go/EventUpdate");
        aBuilder.addHidden ("ID", aResponseObject.getIdAsString ());
        Snippets.generateEventInfo (aBuilder, aResponseObject);

        aBuilder.addRule ();

        // TODO : add a link to remove the location interest.

        Snippets.generateInvitationList (aBuilder, aResponseObject);

        // TODO : If the current user is the owner, add here a collapsible view
        // that shows the remaining locationinterests, and the New Invitation
        // List.

        if (canChange)
        {
            aBuilder.addRule ();
            Snippets.generateLocationInterestList (aBuilder, aResponseObject.getLocation (), aResponseObject);
            Snippets.generateNewInvitationList (aBuilder);
            aBuilder.addRule ();
            aBuilder.addSubmitButton ("OK", "Change");
        }
        aBuilder.closeForm ();

        aResponseObject.getLocation ().generateGoogleMap (aBuilder);

        aBuilder.closeDiv ();

    }

    @Override
    protected void formatBottomAsSimpleDesktopHtml (HtmlBuilder aBuilder, Event aResponseObject) throws Exception
    {
        aBuilder.openDiv ("bottom");
        // TODO : This should go in a "NonHomeServlet"
        aBuilder.addAnchor ("/go/HomeInfo", "Back to home screen");
        super.formatBottomAsSimpleDesktopHtml (aBuilder, aResponseObject);
        aBuilder.closeDiv ();
    }

    @Override
    protected Event generateResponseObject (HttpServletRequest aRequest) throws Exception
    {
        return getReferencedEvent ();
    }

    protected Event getReferencedEvent () throws Exception
    {
        return Event.load (getDatabase (), requireReferenceId ());
    }

    @Override
    protected boolean hasWritePermission (Event aResponseObject)
    {
        return isUser (aResponseObject.getOwnerId ());
    }

    protected boolean isValidEmail (String aEmail)
    {
        return aEmail.contains ("@");
    }

    protected void updateEvent (Event aEvent) throws Exception
    {
        if (!requireWritePermission (aEvent))
        {
            return;
        }

        try
        {
            Calendar c = aEvent.getCalendar ();
            parseRequiredDate ("DATE", c);
            parseRequiredTime ("TIME1", c);
            aEvent.setCalendar (c);
        }
        catch (Exception e)
        {
        }

        RequestBeanSetter s = new RequestBeanSetter (getRequest (), aEvent);
        s.set ("Field11", "FIELD11");
        s.set ("Field12", "FIELD12");
        s.set ("Field13", "FIELD13");
        s.set ("Field14", "FIELD14");
        s.set ("Field21", "FIELD21");
        s.set ("Field22", "FIELD22");
        s.set ("Field23", "FIELD23");
        s.set ("Field24", "FIELD24");
        s.set ("Comment", "COMMENT");
    }

    protected void updateGuests (Event e)
    {
        if (!requireWritePermission (e))
        {
            return;
        }

        for (LocationInterest li : e.getLocation ().getInterests ().getElements ())
        {
            if (getParameter ("INV_" + li.getGuest ().getIdAsString ()) != null)
            {
                e.addGuest (li);
            }
        }

        // TODO : probably no need for this...

        for (Invitation i : e.getInvitations ().getElements ())
        {
            if (getParameter ("INV_" + i.getIdAsString ()) != null)
            {
                i.setInvited (true);
            }
        }

        // TODO : also use the NEWNAME_ parameter...

        for (int i = 0; i < 4; i++)
        {
            String newEmail = getParameter ("NEWEMAIL_" + Long.toString (i));
            if (newEmail != null && isValidEmail (newEmail))
            {
                Person intendedGuest = Person.accessByEmail (getDatabase (), newEmail);
                LocationInterest li = e.getInterest (intendedGuest);
                if (li != null)
                {
                    e.addGuest (li);
                }

            }

        }

    }

}
